public class ArrList<T> {
    // 初始长度
    private static final int DEFAULT_CAPACITY = 10;
    // 存储数据的数组
    private T[] data;
    // 记录元素个数
    private int size;

    public ArrList() {
        this(DEFAULT_CAPACITY);
    }

    /**
     * 可以指定初始容量的构造函数
     *
     * @param capacity 容量
     */
    public ArrList(int capacity) {
        // Java无法直接创建泛型数组，需要强制转换
        data = (T[]) new Object[capacity];
        size = 0;
    }

    /**
     * 计算存储的元素个数
     *
     * @return 元素个数
     */
    public int size() {
        return size;
    }

    /**
     * 判断是否为空
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 获取指定位置的元素
     *
     * @param index 索引位置
     * @return 元素
     */
    public T get(int index) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return data[index];
    }

    /**
     * 扩容
     *
     * @param newCapacity 新容量大小
     */
    private void ensureCapacity(int newCapacity) {
        if (newCapacity > size()) {
            var oldData = data;
            data = (T[]) new Object[newCapacity];
            // 复制数组
            System.arraycopy(oldData, 0, data, 0, size());
        }
    }

    /**
     * 指定位置插入元素
     *
     * @param index 索引位置
     * @param item  待插入数据
     */
    public void insert(int index, T item) {
        if (index < 0 || index > size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        if (data.length == size()) {
            ensureCapacity(size() * 2);
        }
        // 将index索引位置之后的数据向后移动
        System.arraycopy(data, index, data, index + 1, size++ - index);
        data[index] = item;
    }

    /**
     * 在末尾插入数据
     *
     * @param item 待插入数据
     */
    public void add(T item) {
        insert(size(), item);
    }

    /**
     * 修改指定位置数据
     *
     * @param index 索引位置
     * @param item  新值
     * @return 旧值
     */
    public T set(int index, T item) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        var oldItem = data[index];
        data[index] = item;
        return oldItem;
    }

    /**
     * 删除指定位置元素
     *
     * @param index 索引位置
     * @return 被删除元素
     */
    public T remove(int index) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        var removeItem = data[index];
        System.arraycopy(data, index + 1, data, index, size() - index);
        size--;
        return removeItem;
    }

    @Override
    public String toString() {
        var result = new StringBuilder("[");
        for (int i = 0; i < size() - 1; i++) {
            result.append(data[i]).append(",");
        }
        result.append(data[size() - 1]).append("]");
        return result.toString();
    }
}